package com.example.admin.config;

import de.codecentric.boot.admin.server.config.AdminServerProperties;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;

import java.util.UUID;

/**
 * @author kaka
 */
@Slf4j
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    public static final String ADMIN = "ADMIN";
    public static final String CLIENT = "CLIENT";
    public static final String CLIENT_USERNAME = "client";
    public static final String CLIENT_PASSWORD = "12345";

    @Resource
    private AdminServerProperties adminServer;
    @Resource
    private SecurityProperties security;

    @Bean
    public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
        SecurityProperties.User user = security.getUser();
        UserDetails adminUser = User
                .withUsername(user.getName())
                .password(passwordEncoder.encode(user.getPassword()))
                .roles(ADMIN)
                .build();
        UserDetails clientUser = User
                .withUsername(CLIENT_USERNAME)
                .password(passwordEncoder.encode(CLIENT_PASSWORD))
                .roles(CLIENT)
                .build();

        return new InMemoryUserDetailsManager(adminUser, clientUser);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler =
                new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
//        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeHttpRequests(auth -> auth
                        // 允许所有用户访问静态资源和登录页
                        .requestMatchers(
                                "/assets/**",
                                "/login**",
                                "/logout**").permitAll()
                        // 控制台页面（如首页、监控详情）,具体能访问接口受include: '*'配置控制
                        .requestMatchers("/actuator/**").permitAll()
                        .requestMatchers("/applications").permitAll()
                        // 实例注册接口允许 CLIENT 访问
                        .requestMatchers(HttpMethod.POST, "/instances").hasAnyRole(ADMIN, CLIENT)
                        .requestMatchers(HttpMethod.DELETE, "/instances/**").hasAnyRole(ADMIN, CLIENT)
                        // 其他请求需认证
                        .anyRequest().authenticated()
                )
                .formLogin(formLogin -> formLogin.loginPage(this.adminServer.path("/login"))
                        .successHandler(successHandler))
                .logout(logout -> {
                    logout.logoutUrl(this.adminServer.path("/logout"))
                            .logoutSuccessUrl("/login?logout")  // 注销后跳转页面
                            .invalidateHttpSession(true)  // 使 Session 失效
                            .deleteCookies("JSESSIONID");  // 删除 Cookie
                })

                // 启用 HTTP Basic，默认行为
                .httpBasic(Customizer.withDefaults())
                .csrf(csrf -> csrf
                        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
                        .ignoringRequestMatchers(
                                this.adminServer.path("/logout"),
                                this.adminServer.path("/instances"),
                                this.adminServer.path("/instances/**")
                        )
                )
        ;
        // 会话管理配置
//        http.sessionManagement(session -> session
//                .maximumSessions(1) // 每个用户最多一个并发会话
//                .maxSessionsPreventsLogin(false) // 如果为 true，则阻止新登录；false 表示踢出旧会话
//                .expiredSessionStrategy(expired -> {
//                    // 处理会话过期的逻辑，如记录日志或重定向到特定页面
//                    expired.getResponse().sendRedirect(adminContextPath + "/login");
//                })
//        );
        http.rememberMe(rememberMe ->
                rememberMe.key(UUID.randomUUID().toString())
                        .tokenValiditySeconds(1209600));
        return http.build();
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}